using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Nim2D.Components;
using Nim2D.Managers;

namespace Nim2D {

	// TODO: ***************
	// TODO: Object Pools! *
	// TODO: ***************

	public class Engine {

		public static Game Game;
		private static GraphicsDeviceManager GraphicsDeviceManager;
		public static SpriteBatch SpriteBatch;
		private static ContentManager ContentManager;

		public Engine(Game game) {
			Game = game;
			GraphicsDeviceManager = new GraphicsDeviceManager(game);
			ContentManager = game.Content;
			ContentManager.RootDirectory = "Content";
			GraphicsDeviceManager.PreferredBackBufferWidth = 1280;
			GraphicsDeviceManager.PreferredBackBufferHeight = 720;
		}

		public void Initialize() {
			// ...
		}

		public void LoadContent() {
			// Go ahead and create the SpriteBatch, as it will be needed for HUD graphics.
			SpriteBatch = new SpriteBatch(Game.GraphicsDevice);

			LoadLevel(); // TODO: this would go inside an input event handler for 'start game'
		}

		public void UnloadContent() {
			// ...
		}

		public void Update(GameTime gameTime) {
			SpriteBatch.Begin();
			for (Vars.Index = 0; Vars.Index < EntityManager.AllEntities.Count; Vars.Index++) {
				Vars.Entity = EntityManager.AllEntities[Vars.Index];
				foreach (var keyValuePair in Vars.Entity.Components) {
					Vars.DictionaryOfComponents = ComponentManager.ComponentDictionaries[keyValuePair.Key]; // Get The dictionary housing this component type.
					Vars.Component = Vars.DictionaryOfComponents[keyValuePair.Value]; // Get the one belonging to this entity.
					Vars.Component.Update(ref Vars.Entity, gameTime); // Update it.
				}
			}
			SpriteBatch.End();
		}

		public void Draw(GameTime gameTime) {
			// This is being handled in Udpate... how to get it here? Does it matter?
		}

		//=====( Begin LevelLoader )=============

		public static Texture2D Blank;

		private void LoadLevel() {

			// Clean up previous level.
			ContentManager.Unload();
			//ComponentManager.ClearDictionaries(); // Remove any old components.
			EntityManager.ResetEntities();

			// Load this level's assets.
			SpriteBatch = new SpriteBatch(Game.GraphicsDevice);
			Blank = ContentManager.Load<Texture2D>("Blank");

			// Create this level's entities.
			EntityManager.CreateGenericBusinessGuy("Generic Business Guy 0", new Vector2(100, 100));
			EntityManager.CreateGenericBusinessGuy("Generic Business Guy 1", new Vector2(200, 100));
			EntityManager.CreateGenericBusinessGuy("Generic Business Guy 2", new Vector2(300, 100));
		}

		//=====( End LevelLoader )===============

	}

}